package utils

import (
	"context"
	"go.uber.org/zap"
	"log"
	"reward-server/global"
	"time"
)

type LcLock struct {
	Key string
	t   time.Duration
}

func NewLcLock(key string, t int) *LcLock {

	return &LcLock{
		Key: key,
		t:   time.Duration(t),
	}
}

// 加锁
func (r *LcLock) Lock() bool {

	zap.S().Info("获取key:%v", r.Key)
	ret := global.RedisDB.Get(context.Background(), r.Key)
	if ret.Val() != "" {
		return false
	}
	if ret.Err().Error() == "redis: nil" {

		// ex:设置默认过期时间秒，防止死锁
		_, errs := global.RedisDB.SetNX(context.Background(), r.Key, `{"lock":1}`, time.Second*r.t).Result()
		if errs != nil {
			return false
		}
		return true
	}
	return false
}

// 解锁
func (r *LcLock) UnLock() int64 {
	nums, err := global.RedisDB.Del(context.Background(), r.Key).Result()
	if err != nil {
		log.Println(err.Error())
		return 0
	}
	return nums
}

//func (r *LcLock) Lock(ctx context.Context) (error, bool) {
//	ret := global.RedisDB.SetNX(ctx, r.Key, r.Value, r.t)
//	if err := ret.Err(); err != nil {
//		zap.S().Errorf("设置 value %s error: %v\n", r.Value, err)
//		return err, false
//	}
//	return nil, ret.Val()
//}
//
//func (r *LcLock) Unlock(ctx context.Context) bool {
//	ret := global.RedisDB.Del(ctx, r.Key)
//	if err := ret.Err(); err != nil {
//		zap.S().Errorf("unlock error:%v ", err)
//		return false
//	}
//	return true
//}
//
//func (r *LcLock) RetryLock() bool {
//	ok := false
//	for !ok {
//		err, t := r.GetTTL()
//		if err != nil {
//			return false
//		}
//		if t > 0 {
//			zap.S().Infof("锁被抢占, %f 秒后重试...\n", (t / r.t).Seconds())
//			time.Sleep(t / r.t)
//		}
//		err, ok = r.Lock(context.Background())
//		if err != nil {
//			return false
//		}
//	}
//	return ok
//}
//
//func (r *LcLock) GetLock() (error, string) {
//
//	zap.S().Info("获取key:%v", r.Key)
//	ret := global.RedisDB.Get(context.Background(), r.Key)
//	if err := ret.Err(); err != nil {
//		zap.S().Info("获取key错误信息:%v", err)
//		return err, ""
//	}
//
//	rt, _ := ret.Bytes()
//	return nil, string(rt)
//}
//
//// 获取锁的过期剩余时间
//func (r *LcLock) GetTTL() (error, time.Duration) {
//
//	ret := global.RedisDB.TTL(context.Background(), r.Key)
//	if err := ret.Err(); err != nil {
//		fmt.Println("get TTL error: ", err)
//		return err, 0
//	}
//	return nil, ret.Val()
//}
//
//func (r *LcLock) threadLock(threadId string) {
//	for {
//		err, _ := r.GetLock()
//		if err != nil && err.Error() == "redis: nil" {
//			// 没有获取到值，说明目前没有人持有锁
//			fmt.Printf("线程 %s 开始加锁\n", threadId)
//			err, ok := r.Lock(context.Background())
//			if err != nil {
//				return
//			}
//			if !ok {
//				if !r.RetryLock() {
//					fmt.Printf("线程 %s 加锁失败\n", threadId)
//					return
//				}
//			}
//			fmt.Printf("线程 %s 已加锁\n", threadId)
//			// 加锁后执行相应操作
//			time.Sleep(5 * time.Second)
//			// 释放锁
//			r.Unlock(context.Background())
//			fmt.Printf("线程 %s 已释放锁\n", threadId)
//			return
//		} else if err != nil {
//			return
//		}
//		err, t := r.GetTTL()
//		if err != nil {
//			return
//		}
//		if t > 0 {
//			fmt.Printf("线程 %s 锁被占用, %f 秒后重试\n", threadId, (t / 10).Seconds())
//			time.Sleep(t / 10)
//		}
//	}
//}
//
////func main() {
////	var r redisClient
////	address := "192.168.1.151:6379"
////	cl := connRedisSingle(address, "")
////	defer cl.Close()
////	r = redisClient(*cl)
////	// 线程1获取锁
////	go r.threadLock("1")
////	//time.Sleep(10 * time.Millisecond)
////	// 线程2获取锁
////	go r.threadLock("2")
////	select {}
////}
